package com.zhanghe.study.ref;

import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.util.Objects;

/**
 * 虚引用测试
 * @author zh
 * @date 2021/6/22 18:26
 * -XX:InitialHeapSize=134217728 -XX:MaxHeapSize=2147483648
 * -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers
 * -XX:+UseCompressedOops -XX:+UseParallelGC
 */
public class TestPhantom {

    public static void main(String[] args) {
        test1();
    }

    public static void test1(){
        TestRef obj = new TestRef();
        obj.setName("张三");
        ReferenceQueue<TestRef> phantomQueue = new ReferenceQueue<>();
        // 创建虚引用，此时ref是通过虚引用指向的obj对象
        // 虚引用必须要和引用队列一起使用，只存在public PhantomReference(T referent, ReferenceQueue<? super T> q)一种构造器
        PhantomReference<TestRef> ref = new PhantomReference<>(obj,phantomQueue);
        System.out.println(obj);
        // ref的get()方法可以获取到所引用的实际对象
        if(ref.get() != null){
            System.out.println(ref.get());
            System.out.println(Objects.requireNonNull(ref.get()).getName());
            // 清除引用
            ref.clear();
            System.out.println(ref.get());

        } else {
            System.out.println("虚引用已经被回收了");
        }

        // 清除强引用
        obj = null;
        // 垃圾回收
        System.gc();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 垃圾回收后，引用队列中就会存在对象
        try {
            Reference<? extends TestRef> remove = phantomQueue.remove();
            if(remove != null){
                System.out.println(remove.get());
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }


        // 输出结果
        //com.zhanghe.study.ref.TestRef@66d3c617
        //虚引用已经被回收了
    }
}
